using System;
using System.Collections;
using System.Data;

using LocalBoard.Domain;

namespace LocalBoard.Persistence.MockAccessor
{
	/// <summary>
	/// Summary description for MockUserRoleAccessor.
	/// </summary>
	public class MockUserRoleAccessor : IUserRoleAccessor, IClubRoleAccessor, IMockAccessor
	{
		private int _oId;
		private DataTable _userRoleTable = new DataTable("UserRole");
		private DataTable _userRole_x_ProfileTable = new DataTable("UserRole_x_Profile");
		private MockAccessorFactory _accessorFactory = new MockAccessorFactory();

		public static readonly MockUserRoleAccessor Instance = new MockUserRoleAccessor();

		private MockUserRoleAccessor()
		{
			_userRoleTable.Columns.Add("Id", typeof(int));
			_userRoleTable.Columns.Add("Name", typeof(string));
			_userRoleTable.Columns.Add("Club_Id", typeof(int));

			_userRole_x_ProfileTable.Columns.Add("UserRole_Id", typeof(int));
			_userRole_x_ProfileTable.Columns.Add("Profile_Id", typeof(int));
			_userRole_x_ProfileTable.Columns.Add("Club_Id", typeof(int));

			Initialize();
		}

		private void Initialize()
		{
			_oId = 0;
			Insert("admin");
		}

		public void ResetDataTable()
		{
			_userRoleTable.Clear();
			_userRole_x_ProfileTable.Clear();
			Initialize();
		}

		public void RemoveRows(int tableIndex, DataRow[] rows)
		{
			throw new NotImplementedException();
		}

		public DataRow[] ExecuteFilter(string filterExpression)
		{
			throw new NotImplementedException();
		}

		#region IUserRoleAccessor Members

		public UserRole Get(int id)
		{
			return Get(id, 0);
		}

		public Hashtable GetAllUserRoles()
		{
			return GetAllClubRoles(0);
		}

		public ArrayList GetRolesByProfileId(int profileId)
		{
			return GetClubRolesByProfileId(profileId, 0);
		}

		public int Insert(string userRoleName)
		{
			return Insert(userRoleName, 0);
		}

		public void Update(UserRole userRole)
		{
			Update(userRole, 0);
		}

		public void Delete(int id)
		{
			Delete(id, 0);
		}

		public void AddRoleToProfile(int roleId, int profileId)
		{
			AddClubRoleToProfile(roleId, profileId, 0);
		}

		public void DeleteRoleFromProfile(int roleId, int profileId)
		{
			DeleteClubRoleFromProfile(roleId, profileId, 0);
		}

		#endregion

		#region IClubRoleAccessor Members

		public void AddClubRoleToProfile(int roleId, int profileId, int clubId)
		{
			if(Get(roleId, clubId) == null)
				throw new ArgumentException("Role id, \"" + roleId.ToString() + "\" is not in the club.", "roleId");
			if(clubId != 0
				&& !_accessorFactory.GetClubProfileAccessor().IsUserInTheClub(profileId, clubId))
				throw new ArgumentException("Profile id, \"" + profileId.ToString() + "\" is not in the club.", "profileId");
			DataRow newRow = _userRole_x_ProfileTable.NewRow();
			newRow["UserRole_Id"] = roleId;
			newRow["Profile_Id"] = profileId;
			newRow["Club_Id"] = clubId;
			_userRole_x_ProfileTable.Rows.Add(newRow);
			_userRole_x_ProfileTable.AcceptChanges();
		}

		public void Delete(int id, int clubId)
		{
			DataRow row = FindUserRoleDataRow(id, clubId);
			if(row!=null)
			{
				_userRoleTable.Rows.Remove(row);
				_userRoleTable.AcceptChanges();
			}
		}

		public void DeleteClubRoleFromProfile(int roleId, int profileId, int clubId)
		{
			string selectStatement = string.Format("Club_Id={0} and UserRole_Id={1} and Profile_Id={2}", clubId, roleId, profileId);
			DataRow[] result = _userRole_x_ProfileTable.Select(selectStatement);
			if(result.Length > 0)
			{
				_userRole_x_ProfileTable.Rows.Remove(result[0]);
				_userRole_x_ProfileTable.AcceptChanges();
			}
		}

		public UserRole Get(int id, int clubId)
		{
			return GetUserRoleFromResultRow(FindUserRoleDataRow(id, clubId));
		}

		public UserRole Get(string roleName, int clubId)
		{
			return GetUserRoleFromResultRow(FindUserRoleDataRow(roleName, clubId));
		}

		public Hashtable GetAllClubRoles(int clubId)
		{
			Hashtable userRoles = new Hashtable();
			string selectStatement = "Club_Id = " + clubId.ToString();
			foreach(DataRow row in _userRoleTable.Select(selectStatement))
			{
				userRoles.Add(DataConverter.GetInteger(row["Id"]), GetUserRoleFromResultRow(row));
			}
			return userRoles;
		}

		public ArrayList GetClubRolesByProfileId(int profileId, int clubId)
		{
			ArrayList userRoleList = new ArrayList();
			string selectStatement = string.Format("Club_Id = {0} And Profile_Id = {1}", clubId.ToString(), profileId.ToString());
			foreach(DataRow row in _userRole_x_ProfileTable.Select(selectStatement))
			{
				userRoleList.Add(Get(DataConverter.GetInteger(row["UserRole_Id"]), clubId));
			}
			return userRoleList;
		}

		public int Insert(string userRoleName, int clubId)
		{
			if(FindUserRoleDataRow(userRoleName, clubId) != null)
				throw new ApplicationException(string.Format("Duplicate role name, \"{0}\" in the club id, \"{1}\"", userRoleName, clubId.ToString()));
			_oId++;
			DataRow newRow = _userRoleTable.NewRow();
			newRow["Id"] = _oId;
			newRow["Name"] = userRoleName;
			newRow["Club_Id"] = clubId;
			_userRoleTable.Rows.Add(newRow);

			return _oId;
		}

		public void Update(UserRole userRole, int clubId)
		{
			DataRow row = FindUserRoleDataRow(userRole.Id, clubId);
			if(row!=null)
			{
				row["Name"] = userRole.Name;
				_userRoleTable.AcceptChanges();
			}
		}

		#endregion

		private DataRow FindUserRoleDataRow(int id, int clubId)
		{
			foreach(DataRow row in _userRoleTable.Rows)
			{
				if(DataConverter.GetInteger(row["Id"])==id && DataConverter.GetInteger(row["Club_Id"])==clubId)
					return row;
			}
			return null;
		}

		private DataRow FindUserRoleDataRow(string roleName, int clubId)
		{
			foreach(DataRow row in _userRoleTable.Rows)
			{
				if(DataConverter.GetString(row["Name"])==roleName && DataConverter.GetInteger(row["Club_Id"])==clubId)
					return row;
			}
			return null;
		}

		private UserRole GetUserRoleFromResultRow(DataRow row)
		{
			if(row == null)
				return null;
			return new UserRole(DataConverter.GetInteger(row["Id"]), DataConverter.GetString(row["Name"]));
		}
	}
}
